package edu.pku.sei.mte.exceptions;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import edu.pku.sei.mte.exceptions.handler.ExceptionHandler;
import edu.pku.sei.mte.utilities.JavaClassLoader;

public class ExceptionRegistry {
	private Map<Class<? extends Exception>, ExceptionHandler> ExceptionMap = new HashMap<Class<? extends Exception>, ExceptionHandler>();
	
	private static Map<String,Class<? extends Exception>> NameToExceptionMap = new HashMap<String,Class<? extends Exception>>();
	
	static {
		NameToExceptionMap.put("MultiValueBindingsException", MultiValueBindingsException.class);
		NameToExceptionMap.put("CreateAfterDeleteException", CreateAfterDeleteException.class);
		NameToExceptionMap.put("DeleteAfterCreateException", DeleteAfterCreateException.class);
		NameToExceptionMap.put("MetaModelConstraintException", MetaModelConstraintException.class);
	}
	
	private Class<? extends Exception> getPredefinedException(String name){
		if(NameToExceptionMap != null)
			return NameToExceptionMap.get(name);
		return null;
	}
	
	private Class<? extends Exception> getUserDefinedExceptions(){
		for(Class<? extends Exception> c : ExceptionMap.keySet()){
			try{
				c.asSubclass(UserDefinedException.class);
			}catch(ClassCastException e){
				continue;
			}
			
		}
		return null;
	}
	
	public void registerException(String name, String filename, String handlername){
		Class<? extends Exception> c = null;
		if(filename != null && !filename.equals("")){
			File file = new File(filename);
			if(!file.exists()){
				System.out.println("exception file:" + filename + " does not exist!");
				file = null;
			} else {
				try{
					c = JavaClassLoader.getInstance().getJavaClass(file);
				}catch(Exception e){
					System.out.println("file " + filename + " is not an Exception class");
					return;
				}
			}
		}
		if(c == null){
			c = getPredefinedException(name);
			if(c == null){
				System.out.println(name + " is not defined");
				return;
			}
		}
		File handlerfile = new File(handlername);
		if(!handlerfile.exists()){
			System.out.println("exception handler:" + handlername + " does not exist!");
			return;
		}
		Object h = JavaClassLoader.getInstance().getJavaClassInstance(handlerfile);
		if(h instanceof ExceptionHandler){
			addExceptionHandler(c, (ExceptionHandler) h);
		}
		return;
	}
	
	public ExceptionHandler getExceptionHandler(Exception e){
		return ExceptionMap.get(e.getClass());
	}
	
	public void addExceptionHandler(Class<? extends Exception> c, ExceptionHandler ehandler){
		ExceptionMap.put(c, ehandler);
	}
	
	public void addExceptionRegistry(ExceptionRegistry er){
		this.ExceptionMap.putAll(er.ExceptionMap);
	}
}
